<?php
/**
 * Created by PhpStorm.
 * User: fengdh
 * Date: 2019/8/12
 * Time: 11:06
 */

namespace search\models;

use business\base\services\DictionaryService;
use business\base\services\QualificationService;
use business\elasticsearch\models\SupplierModel;
use common\utils\StringUtils;

class SupplierSearchForm extends BaseSearchForm
{
    /**
     * @var string 供应商id
     */
    public $supplierId;
    /**
     * @var int 所在地区
     */
    public $location;
    /**
     * @var int 供应商类型: 3厂商，4代理
     */
    public $supplierType;
    /**
     * @var string 服务资料
     */
    public $qualify;
    /**
     * @var int 成功案例数
     */
    public $projectCount;
    /**
     * @var int 供应商注册地址
     */
    public $registerLocation;
    /**
     * @var string 供应商注册资金
     */
    public $regCapital;
    /**
     * @var int 成立年限
     */
    public $year;
    /**
     * @var int 注册资金排序
     */
    public $regSort;
    /**
     * @var int 成立年限排序
     */
    public $yearSort;

    /**
     * @var int 案例排序
     */
    public $caseSort;
    /**
     * @var int 是否金牌
     */
    public $isGoldenSupplier;
    /**
     * @var int 是否白金
     */
    public $isPlatinumSupplier;
    /**
     * @var int 是否钻石
     */
    public $isDiamondSupplier;
    /**
     * @var string 供应商名称
     */
    public $companyName;

    public $hasCategoryWords = false;

    public function rules()
    {
        return [
            [array_keys($this->getAttributes()), 'safe'],
        ];
    }

    public function search()
    {
        if (!empty($this->keyword)) {
            $this->hasCategoryWords();
        }

        $query = [];
        $condition = $this->constructCondition($this->constructFilter($query));
        $query = SupplierModel::find()->query($condition);

        //高亮处理
        $highlight = [
            'pre_tags' => ['<em class="_high">'],
            'post_tags' => ['</em>'],
            "fields"=>[
                "companyName" => new \stdClass(),
                'basicCategoryName' => new \stdClass(),
                'companyIntro' => new \stdClass(),
            ]
        ];
        $query->highlight($highlight);

        //注册资金排序
        if (isset($this->regSort) && is_numeric($this->regSort)) {
            $regSort = intval($this->regSort) == 0 ? SORT_ASC : SORT_DESC;
            $query->orderBy(['regCapital'=>$regSort]);
        }
        //成立年限排序
        if (isset($this->yearSort) && is_numeric($this->yearSort)) {
            $yearSort = intval($this->yearSort) == 0 ? SORT_ASC : SORT_DESC;
            $query->orderBy(['establishYear'=>$yearSort]);
        }
        //案例排序
        if (isset($this->caseSort) && is_numeric($this->caseSort)) {
            $caseSort = intval($this->caseSort) == 0 ? SORT_ASC : SORT_DESC;
            $query->orderBy(['projectCount'=>$caseSort]);
        }
        $total = $query->count();

        //分页处理
        $query->offset(($this->page - 1) * $this->pageSize)->limit($this->pageSize);
        $data = $query->asArray()->all();

        //数据处理
//        $result = ['resultNum' => $total, 'resultSet' => [], 'popularizeSupplier' => [], 'relatedCategory' => [], 'level3Category' => []];
        $result = ['resultNum' => $total, 'resultSet' => [], 'popularizeSupplier' => [], 'relatedCategory' => []];
        foreach ($data as $dv) {
            $tmp = $dv['_source'];
            if (!empty($dv['highlight'])) {
                foreach ($dv['highlight'] as $key => $value) {
                    if ($key == 'basicCategoryName') {
                        $tmp['basicCategoryNameHL'] = StringUtils::highlightString(!empty($tmp['basicCategoryName']) ? $tmp['basicCategoryName'] : [], $this->keyword);
                    } else {
                        $tmp[$key . 'HL'] = isset($value[0]) ? $value[0] : '';
                    }
                }
            }
            //@todo 发现有部分数据没有supplierId字段，先临时处理，后续排查
            $tmp['supplierId'] = (empty($tmp['supplierId']) && !empty($dv['_id'])) ? $dv['_id'] : $tmp['supplierId'];

            //@todo 重庆美心贝斯特门窗股份有限公司（g163055）的奇葩需求，该公司集团买了3个钻石，但要求该公司在搜索列表中不显示钻石标签；
            //@todo 需求来源学建,且确认后续不会有这种需求，所以先在代码里面做处理
            if ($tmp['supplierId'] == 'G163055') {
                $tmp['isDiamondSupplier'] = 0;
            }

            $result['resultSet'][] = $tmp;
        }

        //推广查询
        if ($this->page == 1 && !empty($this->keyword)) {
            $result["popularizeSupplier"] = $this->selectPopularizeSupplier();
        }

        //添加搜索记录
        if ((int)$this->page === 1) {
            $this->addSearchRecord($this->keyword, $this->keyword, $total, "supplier",
                $this->portal);
        }

        return $result;
    }

    private function constructFilter($query)
    {
        //公司服务区域(项目所在地)过滤
        if (!empty($this->location)) {
            $location = [$this->location];
            $dictionaryService = new DictionaryService();
            $region = $dictionaryService->getRegionHierarchyByCode($location);
            if (!empty($region) && !empty($region->childRegionNodes)) {
                foreach ($region->childRegionNodes as $childRegion) {
                    $location[] = $childRegion->code;
                }
            }
            $location = implode(',', $location);
            $query['function_score']['query']['bool']['filter'][] = SupplierModel::serviceLocationCode($location);
        }

        //供应商类型过滤
        if (!empty($this->supplierType)) {
            $query['function_score']['query']['bool']['filter'][] = SupplierModel::supplierType($this->supplierType);
        }

        //服务资质过滤
        if (!empty($this->qualify)) {
            $quaService = new QualificationService();
            $qualifyCodeList = explode(",", $this->qualify);
            foreach ($qualifyCodeList as $qualifyCode) {
                $qualify = explode("-", $qualifyCode);
                if (count($qualify) != 2) {
                    continue;
                }
                $qualifyLevel = $quaService->getQualificationLevel(['level_code' => $qualify[1]]);
                $query['function_score']['query']['bool']['filter'][] = [
                    'term' => ['qualification_'.$qualify[0] => $qualifyLevel->Priority]
                ];
            }
        }

        //成功案例过滤
        if (!empty($this->projectCount)) {
            $projectCountArray = explode(",", $this->projectCount);
            if (count($projectCountArray) > 1) {
                $projectCountMin = intval($projectCountArray[0]);
                $projectCountMax = intval($projectCountArray[1]);
            } else {
                $projectCountMin = intval($projectCountArray[0]);
                $projectCountMax = null;
            }
            $query['function_score']['query']['bool']['filter'][] = SupplierModel::projectCount($projectCountMin, $projectCountMax);
        }

        //公司注册地过滤
        if (!empty($this->registerLocation)) {
            $registerLocationCode = [$this->registerLocation];
            $dictionaryService = new DictionaryService();
            $region = $dictionaryService->getRegionHierarchyByCode($registerLocationCode);
            if (!empty($region) && !empty($region->childRegionNodes)) {
                foreach ($region->childRegionNodes as $childRegion) {
                    $registerLocationCode[] = $childRegion->code;
                }
            }
            $registerLocationCode = implode(',', $registerLocationCode);
            $query['function_score']['query']['bool']['filter'][] = SupplierModel::regLocationCode($registerLocationCode);
        }

        //一级分类code查询过滤
        if (!empty($this->codeLevel1)) {
            $query['function_score']['query']['bool']['filter'][] = SupplierModel::operationCategoryCode($this->codeLevel1);
        }

        //二级分类code查询过滤
        if (!empty($this->codeLevel2)) {
            $query['function_score']['query']['bool']['filter'][] = SupplierModel::operationCategoryCode($this->codeLevel2, 2);
        }

        //三级分类code查询过滤
        if (!empty($this->codeLevel3)) {
            $codeLevel3 = explode(",", $this->codeLevel3);
            $query['function_score']['query']['bool']['filter'][] = SupplierModel::operationCategoryCode($codeLevel3, 3);
        }

        //注册资金过滤
        if (!empty($this->regCapital)) {
            $regCapitalArray = explode(",", $this->regCapital);
            if (count($regCapitalArray) > 1) {
                $regCapitalMin = intval($regCapitalArray[0]);
                $regCapitalMax = intval($regCapitalArray[1]);
            } else {
                $regCapitalMin = intval($regCapitalArray[0]);
                $regCapitalMax = null;
            }
            $query['function_score']['query']['bool']['filter'][] = SupplierModel::regCapital($regCapitalMin, $regCapitalMax);
        }

        //成立年限过滤
        if (!empty($this->year) && is_numeric($this->year)) {
            $year = intval($this->year);
            $currentYear = intval(date('Y'));
            $to_year = $currentYear - $year;
            $query['function_score']['query']['bool']['filter'][] = [
                ['range' => ['establishYear' => ['to' => $to_year]]]
            ];
        }
        //金牌供应商过滤
        if(!empty($this->isGoldenSupplier) && is_numeric($this->isGoldenSupplier)){
            $query['function_score']['query']['bool']['filter'][] = ['term' => ['isGoldenSupplier' => 1]];
            $query['function_score']['query']['bool']['filter'][] = ['term' => ['isPlatinumSupplier' => 0]];
            $query['function_score']['query']['bool']['filter'][] = ['term' => ['isDiamondSupplier' => 0]];
        }
        //铂金供应商过滤
        if(!empty($this->isPlatinumSupplier) && is_numeric($this->isPlatinumSupplier)){
            $query['function_score']['query']['bool']['filter'][] = ['term' => ['isPlatinumSupplier' => 1]];
            $query['function_score']['query']['bool']['filter'][] = ['term' => ['isDiamondSupplier' => 0]];
        }
        //钻石供应商过滤
        if(!empty($this->isDiamondSupplier) && is_numeric($this->isDiamondSupplier)){
            $query['function_score']['query']['bool']['filter'][] = ['term' => ['isDiamondSupplier' => 1]];
        }
        //通过公司名精确匹配
        if(!empty($this->companyName)){
            $query['function_score']['query']['bool']['filter'][] = ['wildcard' => ['companyName.keyword' => '*'.$this->companyName.'*']];
        }

        return $query;
    }

    private function constructCondition($query)
    {
        if ($this->hasCategoryWords) {
            $query['function_score']['query']['bool']['must'][] = ['match' => ['basicCategoryName' => ['query' => $this->keyword, 'boost'=>2]]];

            $query['function_score']['functions'] = [
                ['script_score' => ['script' => "doc['regCapital'].value>10000 ? 4 : doc['regCapital'].value/2500"]],
                ['script_score' => ['script' => "doc['isDiamondSupplier'].value==1 ? 40 : 0"]],   //是否砖石
                ['script_score' => ['script' => "doc['isPlatinumSupplier'].value==1 ? 20 : 0"]],   //是否铂金
                ['script_score' => ['script' => "doc['isGoldenSupplier'].value==1 ? 10 : 0"]],   //是否金牌
                ['script_score' => ['script' => "doc['isTop'].value==1 ? 20 : 0"]],   //是否十强
                ['script_score' => ['script' => "doc['isFamousSupplier'].value==1 ? 3 : 0"]],    //是否知名(网络名企)
                ['script_score' => ['script' => "doc['projectCount'].value>60 ? 5 : doc['projectCount'].value/12"]],
                ['script_score' => ['script' => "doc['recommendCount'].value>50 ? 5 : doc['recommendCount'].value/10"]],
                ['script_score' => ['script' => "doc['inStorageCount'].value>200 ? 5 : doc['inStorageCount'].value/40"]],
            ];
        } else {
            if (!empty($this->keyword)) {
                $query['function_score']['query']['bool']['should'] = [
                    ['match' => ['shortName' => ['query' => $this->keyword]]],
                    ['match' => ['companyName' => ['query' => $this->keyword, 'boost'=>35]]],
                    ['match' => ['basicCategoryName' => ['query' => $this->keyword, 'boost'=>30]]],
                    ['match' => ['companyIntro' => ['query' => $this->keyword, 'boost'=>2]]],
                    ['match_phrase' => ['companyName' => ['query' => $this->keyword, 'boost'=>1000]]],
                ];
            }
            $query['function_score']['functions'] = [
                ['filter' => ['term' => ['hasEnoughRegCapital' => true]], 'weight' => 2], //注册资本是否大于1000W
                ['filter' => ['term' => ['isDiamondSupplier' => 1]], 'weight' => 40],   //是否砖石
                ['filter' => ['term' => ['isPlatinumSupplier' => 1]], 'weight' => 20],   //是否铂金
                ['filter' => ['term' => ['isGoldenSupplier' => 1]], 'weight' => 10],   //是否金牌
                ['filter' => ['term' => ['isStoraged' => true]], 'weight' => 10],   //是否入库
                ['filter' => ['term' => ['isTop' => 1]], 'weight' => 30],   //是否十强
                ['filter' => ['term' => ['isFamousSupplier' => 1]], 'weight' => 2],    //是否知名(网络名企)
//                ['script_score' => ['script' => "doc['hasEnoughRegCapital'].value==true ? 2 : 0"]], //注册资本是否大于1000W
//                ['script_score' => ['script' => "doc['isDiamondSupplier'].value==1 ? 40 : 0"]],   //是否砖石
//                ['script_score' => ['script' => "doc['isPlatinumSupplier'].value==1 ? 20 : 0"]],   //是否铂金
//                ['script_score' => ['script' => "doc['isGoldenSupplier'].value==1 ? 10 : 0"]],   //是否金牌
//                ['script_score' => ['script' => "doc['isStoraged'].value==true ? 10 : 0"]],   //是否入库
//                ['script_score' => ['script' => "doc['isTop'].value==1 ? 30 : 0"]],   //是否十强
//                ['script_score' => ['script' => "doc['isFamousSupplier'].value==1 ? 2 : 0"]],    //是否知名(网络名企)
            ];
        }
        $query['function_score']['score_mode'] = 'sum';
        return $query;
    }

    /**
     * 判断搜索关键词是否是分类词
     * @throws \yii\db\Exception
     */
    private function hasCategoryWords()
    {
        $sql = "select * from `b2b_parameter`.`bsp_basic_forest` where category_status=1 and category_name like '%".$this->keyword."%'";
        $data = \Yii::$app->db->createCommand($sql)->queryAll();
        $this->hasCategoryWords = empty($data) ? false : true;
    }

    /**
     * 推广搜索
     * @return mixed
     */
    private function selectPopularizeSupplier()
    {
        $keywords = StringUtils::escapeSolrQueryChars($this->keyword);
        $condition = $this->constructFilter([]);
        $condition['function_score']['query']['bool']['filter'][] = ['term' => ['supplierKeywords' => $keywords]];
        $query = SupplierModel::find()->query($condition);
        $result = $query->limit(1)->asArray()->all();
        return isset($result[0]['_source']) ? $result[0]['_source'] : [];
    }

}